home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / bin / tzselect < prev    next >
Text File  |  2006-04-25  |  7KB  |  309 lines

  1. #! /bin/bash
  2.  
  3. # '@(#)tzselect.ksh    1.8'
  4.  
  5. # Ask the user about the time zone, and output the resulting TZ value to stdout.
  6. # Interact with the user via stderr and stdin.
  7.  
  8. # Contributed by Paul Eggert.
  9.  
  10. # Porting notes:
  11. #
  12. # This script requires several features of the Korn shell.
  13. # If your host lacks the Korn shell,
  14. # you can use either of the following free programs instead:
  15. #
  16. #    <a href=ftp://ftp.gnu.org/pub/gnu/>
  17. #    Bourne-Again shell (bash)
  18. #    </a>
  19. #
  20. #    <a href=ftp://ftp.cs.mun.ca/pub/pdksh/pdksh.tar.gz>
  21. #    Public domain ksh
  22. #    </a>
  23. #
  24. # This script also uses several features of modern awk programs.
  25. # If your host lacks awk, or has an old awk that does not conform to Posix.2,
  26. # you can use either of the following free programs instead:
  27. #
  28. #    <a href=ftp://ftp.gnu.org/pub/gnu/>
  29. #    GNU awk (gawk)
  30. #    </a>
  31. #
  32. #    <a href=ftp://ftp.whidbey.net/pub/brennan/>
  33. #    mawk
  34. #    </a>
  35.  
  36.  
  37. # Specify default values for environment variables if they are unset.
  38. : ${AWK=awk}
  39. : ${TZDIR=/usr/share/zoneinfo}
  40.  
  41. # Check for awk Posix compliance.
  42. ($AWK -v x=y 'BEGIN { exit 123 }') </dev/null >/dev/null 2>&1
  43. [ $? = 123 ] || {
  44.     echo >&2 "$0: Sorry, your \`$AWK' program is not Posix compatible."
  45.     exit 1
  46. }
  47.  
  48. # Make sure the tables are readable.
  49. TZ_COUNTRY_TABLE=$TZDIR/iso3166.tab
  50. TZ_ZONE_TABLE=$TZDIR/zone.tab
  51. for f in $TZ_COUNTRY_TABLE $TZ_ZONE_TABLE
  52. do
  53.     <$f || {
  54.         echo >&2 "$0: time zone files are not set up correctly"
  55.         exit 1
  56.     }
  57. done
  58.  
  59. newline='
  60. '
  61. IFS=$newline
  62.  
  63.  
  64. # Work around a bug in bash 1.14.7 and earlier, where $PS3 is sent to stdout.
  65. case $(echo 1 | (select x in x; do break; done) 2>/dev/null) in
  66. ?*) PS3=
  67. esac
  68.  
  69.  
  70. # Begin the main loop.  We come back here if the user wants to retry.
  71. while
  72.  
  73.     echo >&2 'Please identify a location' \
  74.         'so that time zone rules can be set correctly.'
  75.  
  76.     continent=
  77.     country=
  78.     region=
  79.  
  80.  
  81.     # Ask the user for continent or ocean.
  82.  
  83.     echo >&2 'Please select a continent or ocean.'
  84.  
  85.     select continent in \
  86.         Africa \
  87.         Americas \
  88.         Antarctica \
  89.         'Arctic Ocean' \
  90.         Asia \
  91.         'Atlantic Ocean' \
  92.         Australia \
  93.         Europe \
  94.         'Indian Ocean' \
  95.         'Pacific Ocean' \
  96.         'none - I want to specify the time zone using the Posix TZ format.'
  97.     do
  98.         case $continent in
  99.         '')
  100.         echo >&2 'Please enter a number in range.';;
  101.         ?*)
  102.         case $continent in
  103.         Americas) continent=America;;
  104.         *' '*) continent=$(expr "$continent" : '\([^ ]*\)')
  105.         esac
  106.         break
  107.         esac
  108.     done
  109.     case $continent in
  110.     '')
  111.         exit 1;;
  112.     none)
  113.         # Ask the user for a Posix TZ string.  Check that it conforms.
  114.         while
  115.             echo >&2 'Please enter the desired value' \
  116.                 'of the TZ environment variable.'
  117.             echo >&2 'For example, GST-10 is a zone named GST' \
  118.                 'that is 10 hours ahead (east) of UTC.'
  119.             read TZ
  120.             $AWK -v TZ="$TZ" 'BEGIN {
  121.                 tzname = "[^-+,0-9][^-+,0-9][^-+,0-9]+"
  122.                 time = "[0-2]?[0-9](:[0-5][0-9](:[0-5][0-9])?)?"
  123.                 offset = "[-+]?" time
  124.                 date = "(J?[0-9]+|M[0-9]+\.[0-9]+\.[0-9]+)"
  125.                 datetime = "," date "(/" time ")?"
  126.                 tzpattern = "^(:.*|" tzname offset "(" tzname \
  127.                   "(" offset ")?(" datetime datetime ")?)?)$"
  128.                 if (TZ ~ tzpattern) exit 1
  129.                 exit 0
  130.             }'
  131.         do
  132.             echo >&2 "\`$TZ' is not a conforming" \
  133.                 'Posix time zone string.'
  134.         done
  135.         TZ_for_date=$TZ;;
  136.     *)
  137.         # Get list of names of countries in the continent or ocean.
  138.         countries=$($AWK -F'\t' \
  139.             -v continent="$continent" \
  140.             -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
  141.         '
  142.             /^#/ { next }
  143.             $3 ~ ("^" continent "/") {
  144.                 if (!cc_seen[$1]++) cc_list[++ccs] = $1
  145.             }
  146.             END {
  147.                 while (getline <TZ_COUNTRY_TABLE) {
  148.                     if ($0 !~ /^#/) cc_name[$1] = $2
  149.                 }
  150.                 for (i = 1; i <= ccs; i++) {
  151.                     country = cc_list[i]
  152.                     if (cc_name[country]) {
  153.                       country = cc_name[country]
  154.                     }
  155.                     print country
  156.                 }
  157.             }
  158.         ' <$TZ_ZONE_TABLE | sort -f)
  159.  
  160.  
  161.         # If there's more than one country, ask the user which one.
  162.         case $countries in
  163.         *"$newline"*)
  164.             echo >&2 'Please select a country.'
  165.             select country in $countries
  166.             do
  167.                 case $country in
  168.                 '') echo >&2 'Please enter a number in range.';;
  169.                 ?*) break
  170.                 esac
  171.             done
  172.  
  173.             case $country in
  174.             '') exit 1
  175.             esac;;
  176.         *)
  177.             country=$countries
  178.         esac
  179.  
  180.  
  181.         # Get list of names of time zone rule regions in the country.
  182.         regions=$($AWK -F'\t' \
  183.             -v country="$country" \
  184.             -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
  185.         '
  186.             BEGIN {
  187.                 cc = country
  188.                 while (getline <TZ_COUNTRY_TABLE) {
  189.                     if ($0 !~ /^#/  &&  country == $2) {
  190.                         cc = $1
  191.                         break
  192.                     }
  193.                 }
  194.             }
  195.             $1 == cc { print $4 }
  196.         ' <$TZ_ZONE_TABLE)
  197.  
  198.  
  199.         # If there's more than one region, ask the user which one.
  200.         case $regions in
  201.         *"$newline"*)
  202.             echo >&2 'Please select one of the following' \
  203.                 'time zone regions.'
  204.             select region in $regions
  205.             do
  206.                 case $region in
  207.                 '') echo >&2 'Please enter a number in range.';;
  208.                 ?*) break
  209.                 esac
  210.             done
  211.             case $region in
  212.             '') exit 1
  213.             esac;;
  214.         *)
  215.             region=$regions
  216.         esac
  217.  
  218.         # Determine TZ from country and region.
  219.         TZ=$($AWK -F'\t' \
  220.             -v country="$country" \
  221.             -v region="$region" \
  222.             -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
  223.         '
  224.             BEGIN {
  225.                 cc = country
  226.                 while (getline <TZ_COUNTRY_TABLE) {
  227.                     if ($0 !~ /^#/  &&  country == $2) {
  228.                         cc = $1
  229.                         break
  230.                     }
  231.                 }
  232.             }
  233.             $1 == cc && $4 == region { print $3 }
  234.         ' <$TZ_ZONE_TABLE)
  235.  
  236.         # Make sure the corresponding zoneinfo file exists.
  237.         TZ_for_date=$TZDIR/$TZ
  238.         <$TZ_for_date || {
  239.             echo >&2 "$0: time zone files are not set up correctly"
  240.             exit 1
  241.         }
  242.     esac
  243.  
  244.  
  245.     # Use the proposed TZ to output the current date relative to UTC.
  246.     # Loop until they agree in seconds.
  247.     # Give up after 8 unsuccessful tries.
  248.  
  249.     extra_info=
  250.     for i in 1 2 3 4 5 6 7 8
  251.     do
  252.         TZdate=$(LANG=C TZ="$TZ_for_date" date)
  253.         UTdate=$(LANG=C TZ=UTC0 date)
  254.         TZsec=$(expr "$TZdate" : '.*:\([0-5][0-9]\)')
  255.         UTsec=$(expr "$UTdate" : '.*:\([0-5][0-9]\)')
  256.         case $TZsec in
  257.         $UTsec)
  258.             extra_info="
  259. Local time is now:    $TZdate.
  260. Universal Time is now:    $UTdate."
  261.             break
  262.         esac
  263.     done
  264.  
  265.  
  266.     # Output TZ info and ask the user to confirm.
  267.  
  268.     echo >&2 ""
  269.     echo >&2 "The following information has been given:"
  270.     echo >&2 ""
  271.     case $country+$region in
  272.     ?*+?*)    echo >&2 "    $country$newline    $region";;
  273.     ?*+)    echo >&2 "    $country";;
  274.     +)    echo >&2 "    TZ='$TZ'"
  275.     esac
  276.     echo >&2 ""
  277.     echo >&2 "Therefore TZ='$TZ' will be used.$extra_info"
  278.     echo >&2 "Is the above information OK?"
  279.  
  280.     ok=
  281.     select ok in Yes No
  282.     do
  283.         case $ok in
  284.         '') echo >&2 'Please enter 1 for Yes, or 2 for No.';;
  285.         ?*) break
  286.         esac
  287.     done
  288.     case $ok in
  289.     '') exit 1;;
  290.     Yes) break
  291.     esac
  292. do :
  293. done
  294.  
  295. case $SHELL in
  296. *csh) file=.login line="setenv TZ '$TZ'";;
  297. *) file=.profile line="TZ='$TZ'; export TZ"
  298. esac
  299.  
  300. echo >&2 "
  301. You can make this change permanent for yourself by appending the line
  302.     $line
  303. to the file '$file' in your home directory; then log out and log in again.
  304.  
  305. Here is that TZ value again, this time on standard output so that you
  306. can use the $0 command in shell scripts:"
  307.  
  308. echo "$TZ"
  309.